/* (C) Copyright 2008 Bill Buckels */

/*
   time2.c by bill buckels

   overlay module for "What Time is It"
   July 1991

   The original layout was plotted using a circle adjusted for
   aspect in the X direction by an aspect ratio multiplier of 1.16.

   The hand routines use this same ratio to provide
   proportional plotting of vectored angles.

   The dohands() function erases the old set of hands and
   plots a new set of hands each time it is called.

   The dohands() function calls the circlepoints() function
   to provide screen coordinates for the clock hands based
   on their length. The screen coordinates are calculated
   from the centre of the clock circle using a sine_cosine
   table and based on the destination quadrant. The result is
   adjusted for aspect as described above.

*/
#include <stdio.h>
#include <fcntl.h>
#include <prodos.h>
#include <sgtty.h>
#include <device.h>
#include <sysfunc.h>


/* the auxmem (ems) library info */
/* graphics library map for library TIME.RIB */


/* lib info for character array created from fragment HOURMENU.BOT */
#define HOURMENU_SIZE   7680
#define HOURMENU_WIDTH  40
#define HOURMENU_HEIGHT 192
#define HOURMENU_OFFSET 0

/* lib info for character array created from fragment TIME0A.RAG */
#define TIME0A_SIZE   1296
#define TIME0A_WIDTH  16
#define TIME0A_HEIGHT 81
#define TIME0A_OFFSET 7680

/* lib info for character array created from fragment TIME1A.RAG */
#define TIME1A_SIZE   3276
#define TIME1A_WIDTH  26
#define TIME1A_HEIGHT 126
#define TIME1A_OFFSET 8976

/* lib info for character array created from fragment TIME2A.RAG */
#define TIME2A_SIZE   3264
#define TIME2A_WIDTH  24
#define TIME2A_HEIGHT 136
#define TIME2A_OFFSET 12252

/* lib info for character array created from fragment ELBOW.RAG */
#define ELBOW_SIZE   96
#define ELBOW_WIDTH  4
#define ELBOW_HEIGHT 24
#define ELBOW_OFFSET 15516

/* lib info for character array created from fragment ELBOW2.RAG */
#define ELBOW2_SIZE   96
#define ELBOW2_WIDTH  4
#define ELBOW2_HEIGHT 24
#define ELBOW2_OFFSET 15612

/* lib info for character array created from fragment DOWNPIPE.RAG */
#define DOWNPIPE_SIZE   64
#define DOWNPIPE_WIDTH  4
#define DOWNPIPE_HEIGHT 16
#define DOWNPIPE_OFFSET 15708

/* lib info for character array created from fragment DOWN2.RAG */
#define DOWN2_SIZE   64
#define DOWN2_WIDTH  4
#define DOWN2_HEIGHT 16
#define DOWN2_OFFSET 15772

/* lib info for character array created from fragment SPOUT.RAG */
#define SPOUT_SIZE   496
#define SPOUT_WIDTH  16
#define SPOUT_HEIGHT 31
#define SPOUT_OFFSET 15836

/* lib info for character array created from fragment SPOUT2.RAG */
#define SPOUT2_SIZE   496
#define SPOUT2_WIDTH  16
#define SPOUT2_HEIGHT 31
#define SPOUT2_OFFSET 16332

/* lib info for character array created from fragment WAVE.RAG */
#define WAVE_SIZE   1704
#define WAVE_WIDTH  24
#define WAVE_HEIGHT 71
#define WAVE_OFFSET 16828

/* lib info for character array created from fragment WAVENO.RAG */
#define WAVENO_SIZE   1704
#define WAVENO_WIDTH  24
#define WAVENO_HEIGHT 71
#define WAVENO_OFFSET 18532

/* lib info for character array created from fragment BOTGLAS.RAG */
#define BOTGLAS_SIZE   580
#define BOTGLAS_WIDTH  10
#define BOTGLAS_HEIGHT 58
#define BOTGLAS_OFFSET 20816

/* lib info for character array created from fragment TIME1B.RAG */
#define TIME1B_SIZE   968
#define TIME1B_WIDTH  22
#define TIME1B_HEIGHT 44
#define TIME1B_OFFSET 21396

/* lib info for character array created from fragment TIME1C.RAG */
#define TIME1C_SIZE   968
#define TIME1C_WIDTH  22
#define TIME1C_HEIGHT 44
#define TIME1C_OFFSET 22364

/* lib info for character array created from fragment TIME1D.RAG */
#define TIME1D_SIZE   912
#define TIME1D_WIDTH  16
#define TIME1D_HEIGHT 57
#define TIME1D_OFFSET 23332

/* lib info for character array created from fragment TOPGLAS.RAG */
#define TOPGLAS_SIZE   580
#define TOPGLAS_WIDTH  10
#define TOPGLAS_HEIGHT 58
#define TOPGLAS_OFFSET 24244

/* lib info for character array created from fragment WORM0.RAG */
#define WORM0_SIZE   408
#define WORM0_WIDTH  8
#define WORM0_HEIGHT 51
#define WORM0_OFFSET 24824

/* lib info for character array created from fragment WORM1.RAG */
#define WORM1_SIZE   408
#define WORM1_WIDTH  8
#define WORM1_HEIGHT 51
#define WORM1_OFFSET 25232

/* lib info for character array created from fragment WORM2.RAG */
#define WORM2_SIZE   408
#define WORM2_WIDTH  8
#define WORM2_HEIGHT 51
#define WORM2_OFFSET 25640

/* lib info for character array created from fragment LIGHTON.RAG */
#define LIGHTON_SIZE   76
#define LIGHTON_WIDTH  4
#define LIGHTON_HEIGHT 19
#define LIGHTON_OFFSET 26048

/* lib info for character array created from fragment LIGHTOFF.RAG */
#define LIGHTOFF_SIZE   76
#define LIGHTOFF_WIDTH  4
#define LIGHTOFF_HEIGHT 19
#define LIGHTOFF_OFFSET 26124

/* lib info for character array created from fragment TIME2B.RAG */
#define TIME2B_SIZE   638
#define TIME2B_WIDTH  22
#define TIME2B_HEIGHT 29
#define TIME2B_OFFSET 26200

int getch();
int randomval();

#define clearscreen() setmem(0x4000,0x2000,0x80)


/* special keys as noted */
/* note that none of the special keys used are affected by caps lock */

#define ESCKEY     27        /* exit current module */
#define ENTERKEY   13        /* initialize command  */
#define SPACEBAR   32        /* same as ENTERKEY    */
#define SOUNDKEY   19        /* sound toggle */

#define THREE      51
#define FIVE       53
extern int multiples;
char *timebuf="  :00"; /* digital clock text */

/* the limits for the multiple choices - default is set to 3 boxes */
/* pressing the number 3 or 5 prior to pressing the spacebar       */
/* or the enter key will flipflop between levels                   */

#define BACKSPACE  8
#define LEFTARROW  8
#define RIGHTARROW 21
#define UPARROW    11
#define DOWNARROW  10
#define DELETE     127
#define CTRLKEY    -64  /* toupper - 64 = ctrl value of a key press */

extern int hourslimit;        /* set to 12 for M0 or 24 for M1 and M2 */
extern int randomhours[5];
extern int randomminutes[5];

#define ON  1
#define OFF 0
extern int soundflag;

#define PUT 0    /* action verbs for putimage */
#define GET 1
#define P_AND 5



    /* locations for the digital clock on the right */
    /* dimension = byte x raster                    */
    /* multiply x 7 to use pixel plotting functions */
int boxcords[6][6]={
                      /* box cords */        /* textcords */
                      32,5,     39, 25,     33, 10,
                      32,40,    39, 60,     33, 45,
                      32,75,    39, 95,     33, 80,
                      32,110,   39, 130,    33, 115,
                      32,145,   39, 165,    33, 150,


                      32,156,   0,  0,      0,  0};

/* use a buffer directly beneath the program */
/* to back-up the clock face                 */
/* buffer size is 640 bytes....              */

extern char *cleanface;

#define  FACEX 12
#define  FACEY 56
#define  FACEHEIGHT 56
#define  FACEWIDTH  10


#define SNL_SIZE   350
#define SNL_WIDTH  10
#define SNL_HEIGHT 35

extern char *SNLBACK;
extern char *LEFTSNL;
extern char *RIGHTSNL;

/* a pointer to the library buffer in memory */
extern char *SNAIL;



ovmain(answers)
int answers;
{

/* position markers */
int pos=5, oldpos=5;

       int done = 0;
       int c, choice,temp=0;



       if(!answers)
       {
       clearscreen();
       lbox(0,0,279,191,0);
       emsputimage(TIME2A_OFFSET,
                   TIME2A_WIDTH,TIME2A_HEIGHT,
                   4,1,0);
       /* put the apple into place */
       emsputimage(WORM0_OFFSET,
                   WORM0_WIDTH,WORM0_HEIGHT,
                   4,139,0);


       /* light the lights */
       dolights(0);

       /* store the clock face in a buffer */
       putimage(cleanface,FACEWIDTH,FACEHEIGHT,FACEX,FACEY,GET);

       /* store the snail position in a buffer */
       /* and put up the first snail           */
       putimage(SNLBACK,SNL_WIDTH,SNL_HEIGHT,
                boxcords[oldpos][0]-10,boxcords[oldpos][1],GET);
       /* put the musical note up */
       noteworthy(1);
       }
       if(answers)dolights(0);

       putimage(LEFTSNL,SNL_WIDTH,SNL_HEIGHT,
                boxcords[oldpos][0]-10,boxcords[oldpos][1],PUT);


       hourslimit=12;
       choice=randomval();

       /* draw the boxes on the right side      */
       /* the minutes are active in this module */
       c=0;
       while(c<multiples)
       {

        if(!answers || c>2 )
        lbox(boxcords[c][0],boxcords[c][1],boxcords[c][2],boxcords[c][3],1);
        c++;
        }

       dohands(randomhours[choice],randomminutes[choice]);



       do
       {
            /* for test purposes  */
            /* on every key press */
            /* display a new time */

            c=getch();
            switch(c)
            {

             case SOUNDKEY:  noteworthy(0);break;

             case UPARROW:   if(pos==0)
                             {
                              if(soundflag)sound(0,0,3);
                              }
                             else pos--;
                             if(pos>=multiples)pos=multiples-1;
                             break;

             case DOWNARROW: if(pos>=(multiples-1))
                             {
                                if(soundflag)sound(0,0,3);
                             }
                             else pos++;
                             break;

             case 27: return 0;

             case SPACEBAR:
             case ENTERKEY:

                      if(choice!=pos || pos==5)
                      {
                        if(soundflag)sound(0,0,3);
                        break;
                        }

                      /* erase the other times */
                      for(c=0;c<multiples;c++)
                      {
                        if(c!=oldpos)
                        plots2(timebuf,boxcords[c][4],boxcords[c][5],0);
                        }

                      /* move the snail down */
                      putimage(SNLBACK,SNL_WIDTH,SNL_HEIGHT,
                         boxcords[oldpos][0]-10,boxcords[oldpos][1],PUT);
                      pos=5;
                      oldpos=5;
                      putimage(SNLBACK,SNL_WIDTH,SNL_HEIGHT,
                         boxcords[oldpos][0]-10,boxcords[oldpos][1],GET);
                      putimage(RIGHTSNL,SNL_WIDTH,SNL_HEIGHT,
                         boxcords[oldpos][0]-10,boxcords[oldpos][1],PUT);

                      if(soundflag)choice=3;
                      else choice=7;
                      answers++;
                      temp++;

                      /* get a reward every 10 times */
                      /* count off the answers */
                      /* light the lights */
                      dolights(answers);
                      if(answers==10||answers==20)
                      {
                        if(answers==20)hourslimit=48;
                        return answers;
                      }
                      for(c=0;c<temp;c++)
                           sound((char)choice,(char)c,1);
                      /* wait for a moment */
                      sound(7,0,10);
                      /* do the next clock in the series */
                      choice=randomval();
                      /* minutes are active */

                      dohands(randomhours[choice],randomminutes[choice]);
                      putimage(LEFTSNL,SNL_WIDTH,SNL_HEIGHT,
                         boxcords[oldpos][0]-10,boxcords[oldpos][1],PUT);


             }
             /* if our position has changed update the snail */
             if(pos!=oldpos)
             {
                putimage(SNLBACK,SNL_WIDTH,SNL_HEIGHT,
                         boxcords[oldpos][0]-10,boxcords[oldpos][1],PUT);
                oldpos=pos;
                putimage(SNLBACK,SNL_WIDTH,SNL_HEIGHT,
                         boxcords[oldpos][0]-10,boxcords[oldpos][1],GET);
                putimage(LEFTSNL,SNL_WIDTH,SNL_HEIGHT,
                         boxcords[oldpos][0]-10,boxcords[oldpos][1],P_AND);


             }
       }
       while(!(done));

}

dolights(answers)
int answers;
{

    int i;



    /* move the eyes */
    emsputimage(TIME2B_OFFSET,
                TIME2B_WIDTH,TIME2B_HEIGHT,
                   4,1,0);


    if(answers>10)answers-=10;
    switch(answers)
    {

      case 0  :    /* light-up all the lights on the first pass */
                for(i=0;i<10;i++)
                   emsputimage(LIGHTON_OFFSET,
                   LIGHTON_WIDTH,LIGHTON_HEIGHT,
                   0,(i*19)+1,PUT);
                   break;
      default :
                   i=answers-1;
                   /* turn-off a light each right answer */
                   emsputimage(LIGHTOFF_OFFSET,
                   LIGHTOFF_WIDTH,LIGHTOFF_HEIGHT,
                   0,(i*19)+1,PUT);
    }
    emsputimage(TIME2A_OFFSET,
                TIME2A_WIDTH,TIME2B_HEIGHT,
                   4,1,0);



}


dohands(hour,minute)
int hour, minute;
{
   /* centre of the circle */
   int x1=116, y1=84, x2,y2;
   /* length of the hands */
   int hourbase=20, minutebase=26;

   /* variables for time update */
   int temp;
   int part1;
   int part2;

   double hourdegrees;
   double minutedegrees;

   /* erase the old hands */
   putimage(cleanface,FACEWIDTH,FACEHEIGHT,FACEX,FACEY,PUT);

   /* update the time */

   temp=0;
   while(temp<multiples)
   {
    /* the old time is erased first for smooth sequencing  */
    plots2(timebuf,boxcords[temp][4],boxcords[temp][5],0);
    temp++;
    }


   temp=0;
   while(temp<multiples)
   {
    /* convert hours to ascii and plot in the appropriate box */
    part1=randomhours[temp]/10;
    part2=randomhours[temp]%10;

    if(part1==0)part1=32;
    else part1+=48;
    if(part2==0 && part1==32)part2=32;
    else part2+=48;

    timebuf[0]=(char)part1;
    timebuf[1]=(char)part2;

    part1=(randomminutes[temp]/10)+48;
    part2=(randomminutes[temp]%10)+48;
    timebuf[3]=(char)part1;
    timebuf[4]=(char)part2;
    plots2(timebuf,boxcords[temp][4],boxcords[temp][5],1);
    temp++;
    }

   minutedegrees=(double)6*minute;

   while(hour>11)hour-=12;
   hourdegrees= (double)30*hour;
   hourdegrees+= (double).5*minute; /* adjust for between hours */

   /* draw the new hands */

   x2=x1;
   y2=y1;
   circlepoints(&x2,&y2,minutebase,minutedegrees);
   /* draw the minute hand */
   drawline(x1,y1,x2,y2,0);

   x2=x1-2;
   y2=y1;
   circlepoints(&x2,&y2,hourbase,hourdegrees);
   /* draw the hour hand */
   drawline(x1-2,y1,x2,y2,3,0);

}

extern int sine_cosine[46][2];

circlepoints(x,y,baselength,fdegrees)
int *x, *y;
int baselength;
float fdegrees;
{
    float xtemp;
    float ytemp;
    int degrees = (int )fdegrees;
    float aspect_h, aspect_v;

    aspect_h = (float)1.16;
    aspect_v = (float)1;

/*  starting at 12 O'clock    */
/* use a switch for the break */


switch(degrees)
{


    default:

    /* within range */
    if(degrees<0 || degrees >359)degrees=0;

    /*  0-45  sin */
    if(degrees < 45)
    {
    xtemp = (float) sine_cosine[degrees][0];
    ytemp = (float) sine_cosine[degrees][1];
    ytemp = ytemp * -1;
    break;
    }

    /* 45-90  cos */
    if(degrees < 90)
    {
    xtemp = (float) sine_cosine[90-degrees][1];
    ytemp = (float) sine_cosine[90-degrees][0];
    ytemp = ytemp * -1;
    break;
    }

   /* 90 - 135 */
   if(degrees < 135)
   {
    xtemp = (float) sine_cosine[degrees-90][1];
    ytemp = (float) sine_cosine[degrees-90][0];
    break;
    }

    /* 135 - 180 */
   if(degrees< 180)
   {
    xtemp = (float) sine_cosine[180-degrees][0];
    ytemp = (float) sine_cosine[180-degrees][1];
    break;
    }

   /* 180 - 225 */
   if(degrees< 225)
   {
    xtemp = (float) sine_cosine[degrees-180][0];
    xtemp = xtemp * -1;
    ytemp = (float) sine_cosine[degrees-180][1];
    break;
    }

   /* 225 - 270 */
   if(degrees< 270)
   {
    xtemp = (float) sine_cosine[270-degrees][1];
    xtemp = xtemp * -1;
    ytemp = (float) sine_cosine[270-degrees][0];
    break;
    }

   /*  270 - 315 */
   if(degrees< 315)
   {
    xtemp = (float) sine_cosine[degrees-270][1];
    xtemp = xtemp * -1;
    ytemp = (float) sine_cosine[degrees-270][0];
    ytemp = ytemp * -1;
    break;
    }

    /* 315 - 360 */
    xtemp = (float) sine_cosine[360-degrees][0];
    xtemp = xtemp * -1;
    ytemp = (float) sine_cosine[360-degrees][1];
    ytemp = ytemp * -1;
    }

    ytemp = ytemp/32767;
    xtemp = xtemp/32767;

    xtemp *= (aspect_h*baselength);
    ytemp *= (aspect_v*baselength);

    *x += (int )xtemp;
    *y += (int )ytemp;

}

